#include "curvabezier.h"



//CurvaBezier::CurvaBezier(QGraphicsScene &s) : Curva(s)
CurvaBezier::CurvaBezier (void)
{
}

CurvaBezier::~CurvaBezier()
{
}

void CurvaBezier::plotSubCurve(QGraphicsScene &s, QPen& p, int index)
{
	QPointF current, next;

	current = _points[index];

	double t = 0;
	double aux;

	for( int i = 1; i <= MAX_STEPS; ++i )
	{
		t = i/(double)MAX_STEPS;

		aux = 1.0 - t;

		next = _points[index]*(aux*aux*aux);
		next += _points[index+1]*(3*(aux*aux)*(t));
		next += _points[index+2]*(3*(aux)*(t*t));
		next += _points[index+3]*(t*t*t);

		_myPlots.append((QGraphicsItem*)s.addLine(QLineF(current, next), p));

		current = next;
	}
}

void CurvaBezier::plotCurve(QGraphicsScene &s, QPen& p)
{
	for( int i = 0; i < _points.size() - 3; i += 3)
	{
		plotSubCurve(s, p, i);
	}
}

void CurvaBezier::plotSteps(QGraphicsScene &s, QPen& p)
{

}

void CurvaBezier::plotControls(QGraphicsScene &s, QPen& p)
{
	for( int i = 0; i < _points.size(); ++i )
	{
		_myPlots.append((QGraphicsItem*)s.addEllipse(_points[i].x()-0.5, _points[i].y()-0.5, 1, 1, p));
	}
}

void CurvaBezier::plotFecho(QGraphicsScene &s, QPen& p)
{
	int r = 200-_plotColor.red();
	int g = 200-_plotColor.green();
	int b = 200-_plotColor.blue();

	p.setColor(QColor(r>=0?r:0, g>=0?g:0, b>=0?b:0));

	for( int i = 1; i < _points.size(); ++i)
	{
		_myPlots.append(s.addLine(QLineF(_points[i-1], _points[i]), p));
	}
}

void CurvaBezier::plot(QGraphicsScene &s, QPen& p, RenderMode renderMode)
{
	QColor prevColor = p.color();

	p.setColor(_plotColor);

	switch(renderMode)
	{
		case CurveMode:
			plotCurve(s, p);
			break;
		case StepMode:
			plotSteps(s, p);
			break;
		case ControlMode:
			plotControls(s, p);
			break;
		case FechoConvexo:
			plotFecho(s, p);
			break;
	}

	p.setColor(prevColor);
}

void CurvaBezier::addPoint (QPointF p)
{
	_points.append (p);
}

int CurvaBezier::removePoint (QPointF *p)
{
	for (int i = 0; i < _points.size(); ++i)
	{
		if (p == &(_points[i]))
		{
			_points.remove (i);
			return true; //!(_points.size()) | 0x2;
		}
	}

	return false; //!(_points.size());
}

void CurvaBezier::clear(QGraphicsScene &s)
{
	for( int i = 0; i < _myPlots.size(); ++i )
	{
		s.removeItem(_myPlots[i]);
		delete _myPlots[i];
	}

	_myPlots.clear();
}

bool CurvaBezier::validate()
{
	qDebug() << "Points : " << _points.size();

	return (_points.size()>=4)?(_points.size()%3 == 1):false;
}

bool CurvaBezier::minimumValidate()
{
	return (_points.size()>=4);
}

void CurvaBezier::read(QDomElement node)
{
	QDomElement p = node.firstChildElement();

	qDebug() << "Loading Bezier Curve...";

	while(!p.isNull())
	{
		if( p.tagName() == "ponto")
		{
			QPointF point = readPoint(p);

			_points.append(point);
		}
		else if( p.tagName() == "cor")
		{
			QColor c = readColor(p);

			_plotColor = c;
		}
		else
		{
			qDebug() << "\t" << "Unknow Tag Name inside Bezier Curve : " << p.tagName();
		}

		p = p.nextSiblingElement();
	}
}

QDomElement CurvaBezier::save(QDomDocument doc)
{
	QDomElement me = doc.createElement("curva");

	me.setAttribute("formato", "bezier");
	me.setAttribute("resolucao", MAX_STEPS);

	for( int i = 0;i < _points.size(); ++i )
	{
		QPointF p = _points[i];

		QDomElement point = doc.createElement("ponto");

		// X
		QDomElement x = doc.createElement("x");
		QDomElement y = doc.createElement("y");

		QDomCharacterData xValue = doc.createTextNode(QString::number(p.x()));
		QDomCharacterData yValue = doc.createTextNode(QString::number(p.y()));

		x.appendChild(xValue);
		y.appendChild(yValue);

		point.appendChild(x);
		point.appendChild(y);

		me.appendChild(point);
	}
	// Cor
	QDomElement cor = doc.createElement("cor");

	QDomElement corR = doc.createElement("r");
	QDomElement corG = doc.createElement("g");
	QDomElement corB = doc.createElement("b");

	QDomCharacterData corRValue = doc.createTextNode(QString::number(_plotColor.red()));
	QDomCharacterData corGValue = doc.createTextNode(QString::number(_plotColor.green()));
	QDomCharacterData corBValue = doc.createTextNode(QString::number(_plotColor.blue()));

	corR.appendChild( corRValue );
	corG.appendChild( corGValue );
	corB.appendChild( corBValue );

	cor.appendChild(corR);
	cor.appendChild(corG);
	cor.appendChild(corB);

	me.appendChild(cor);


	return me;
}

QPointF* CurvaBezier::selectPoint (QPointF &p, const double precision)
{
	QPointF diff;

	for (int i = 0; i < _points.size(); ++i)
	{
		diff = _points[i] - p;
		diff.setX (diff.x() * diff.x());
		diff.setY (diff.y() * diff.y());

		if (diff.manhattanLength() <= precision)
			return &(_points[i]);
	}

	return NULL;
}

QImage CurvaBezier::draw()
{
	QImage ret;



	return ret;
}
